using Coldairarrow.Util;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;
using System;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace Coldairarrow.Api
{
    /// <summary>
    /// Basic认证校验
    /// </summary>
    public class CheckBasicAuthAttribute : BaseActionFilterAsync
  {
    private static readonly int _errorCode = 401;

    public override async Task OnActionExecuting(ActionExecutingContext context)
    {
      try
      {
        var request = context.HttpContext.Request;
        var authHeader = request.Headers["Authorization"];
        if (!authHeader.IsNullOrEmpty())
        {
          var authHeaderVal = AuthenticationHeaderValue.Parse(authHeader);

          // RFC 2617 sec 1.2, "scheme" name is case-insensitive
          if (authHeaderVal.Scheme.Equals("basic",
                  StringComparison.OrdinalIgnoreCase) &&
              authHeaderVal.Parameter != null)
          {
            AuthenticateUser(authHeaderVal.Parameter);
          }
        }
        else
        {
          context.Result = Error("缺少认证信息", _errorCode);
          return;
        }
      }
      catch (Exception ex)
      {
        context.Result = Error(ex.Message, _errorCode);
      }

      await Task.CompletedTask;
    }

    private void AuthenticateUser(string credentials)
    {
      try
      {
        var encoding = Encoding.UTF8;
        credentials = encoding.GetString(Convert.FromBase64String(credentials));

        int separator = credentials.IndexOf(':');
        string name = credentials.Substring(0, separator);
        string password = credentials.Substring(separator + 1);

        if (CheckPassword(name, password) == false)
        {
          throw new Exception("用户名或密码出错!");
        }
      }
      catch (FormatException)
      {
        throw new Exception("验证信息格式出错");
      }
    }

    private bool CheckPassword(string username, string password)
    {
      string appUsername = ConfigHelper.Configuration.GetSection("SyncDataBasicAuth").GetValue<string>("username");

      string appPassword = ConfigHelper.Configuration.GetSection("SyncDataBasicAuth").GetValue<string>("password");
      return username == appUsername && password == appPassword;
    }
  }
}